from extensions import db
from datetime import datetime
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash

# 用户模型
class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    password_hash = db.Column(db.String(128), nullable=False)
    role = db.Column(db.String(20), nullable=False, default='operator')  # 角色：admin 或 operator
    name = db.Column(db.String(100), nullable=True)  # 用户姓名
    gender = db.Column(db.String(10))  # 性别：male 或 female
    birth_date = db.Column(db.Date)  # 出生日期
    phone = db.Column(db.String(20))  # 联系电话
    email = db.Column(db.String(100), unique=True)  # 邮箱
    address = db.Column(db.Text)  # 地址
    avatar = db.Column(db.String(255))  # 头像地址
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    def set_password(self, password):
        self.password_hash = generate_password_hash(password)
        
    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

# 供应商模型
class Supplier(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)  # 供应商名称
    contact_person = db.Column(db.String(50))  # 联系人
    phone = db.Column(db.String(20))  # 联系电话
    email = db.Column(db.String(100))  # 邮箱
    address = db.Column(db.Text)  # 地址
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关联关系
    products = db.relationship('Product', backref='supplier', lazy=True)

# 商品分类模型
class Category(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)  # 分类名称
    description = db.Column(db.Text)  # 分类描述
    parent_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=True)  # 父分类ID
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 自关联关系
    children = db.relationship('Category', backref=db.backref('parent', remote_side=[id]), lazy=True)
    products = db.relationship('Product', backref='category', lazy=True)

# 商品模型
class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)  # 商品名称
    sku = db.Column(db.String(50), unique=True, nullable=False)  # 商品编码
    description = db.Column(db.Text)  # 商品描述
    category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=True)  # 分类ID
    supplier_id = db.Column(db.Integer, db.ForeignKey('supplier.id'), nullable=True)  # 供应商ID
    unit_price = db.Column(db.Float, nullable=False, default=0.0)  # 单价
    cost_price = db.Column(db.Float, nullable=False, default=0.0)  # 成本价
    unit = db.Column(db.String(20), nullable=False, default='个')  # 单位
    min_stock = db.Column(db.Integer, default=0)  # 最小库存
    max_stock = db.Column(db.Integer, default=1000)  # 最大库存
    image = db.Column(db.String(255))  # 商品图片
    status = db.Column(db.String(20), default='active')  # 状态：active 或 inactive
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关联关系
    inventory_records = db.relationship('Inventory', backref='product', lazy=True)
    stock_in_records = db.relationship('StockIn', backref='product', lazy=True)
    stock_out_records = db.relationship('StockOut', backref='product', lazy=True)

# 库存记录模型
class Inventory(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
    current_stock = db.Column(db.Integer, nullable=False, default=0)  # 当前库存
    reserved_stock = db.Column(db.Integer, default=0)  # 预留库存
    available_stock = db.Column(db.Integer, default=0)  # 可用库存
    last_updated = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

# 入库记录模型
class StockIn(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
    quantity = db.Column(db.Integer, nullable=False)  # 入库数量
    unit_price = db.Column(db.Float, nullable=False)  # 入库单价
    total_amount = db.Column(db.Float, nullable=False)  # 总金额
    batch_number = db.Column(db.String(50))  # 批次号
    operator_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)  # 操作员
    notes = db.Column(db.Text)  # 备注
    status = db.Column(db.String(20), default='completed')  # 状态：pending, completed, cancelled
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关联关系
    operator = db.relationship('User', backref='stock_in_operations', lazy=True)

# 出库记录模型
class StockOut(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
    quantity = db.Column(db.Integer, nullable=False)  # 出库数量
    unit_price = db.Column(db.Float, nullable=False)  # 出库单价
    total_amount = db.Column(db.Float, nullable=False)  # 总金额
    operator_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)  # 操作员
    notes = db.Column(db.Text)  # 备注
    status = db.Column(db.String(20), default='completed')  # 状态：pending, completed, cancelled
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关联关系
    operator = db.relationship('User', backref='stock_out_operations', lazy=True)
